/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef __NOISE_DATA_SOURCE_WAVEFILE_H__
#define __NOISE_DATA_SOURCE_WAVEFILE_H__

#include <SharedRep.h>
#include "DataSource.h"
#include <filesystem/String.hpp>
#include <vector>

#include <logs/Log.h>

namespace liba
{
namespace noise
{

class WaveFileRep
{
	int src_bytes;
	int src_bits;
	int src_stride;
	int channels_count;
	int frequency;
	std::vector<char> wave_data;
	bool valid_flag;
public:
	explicit WaveFileRep( const filesystem::String & file_name );
	~WaveFileRep();
	bool is_valid()const
	{
		return valid_flag;
	}
	int get_length()const
	{
		return wave_data.size() / src_stride;
	}
	int get_frequency()const
	{
		return frequency;
	}
	bool has_native(DataSource::Type channel);
	void get_data(int current_sample, int next_sample, DataSource::Type channel, void * dst, int dst_stride, int dst_bits);
};

class DataSourceWaveFile : public DataSource, private Shared<filesystem::String, WaveFileRep>
{
	int current_sample;
	int next_sample;
public:
	explicit DataSourceWaveFile( const filesystem::String & file_name )
	:	current_sample( 0 ),
		next_sample( 0 )
	{
		load_rep( file_name );
	}
	virtual ~DataSourceWaveFile()
	{}
	bool is_valid()const
	{
		return get_rep()->is_valid();
	}
	virtual int get_frequency()
	{
		return get_rep()->get_frequency();
	}
	virtual bool has_native(Type channel)
	{
		return get_rep()->has_native( channel );
	}
	virtual int get_length()
	{
		return get_rep()->get_length();
	}
	virtual int decode(int samples)
	{
		const int length = get_rep()->get_length();
		current_sample = next_sample;
//		logs::log() << "liba::noise::DataSourceWaveFile::decode() current_sample = " << current_sample;
		if( current_sample == length )
		{
//			logs::log() << " return 0\n";
			next_sample = 0;
			return 0;
		}
		const int real_samples = std::min( length - current_sample, samples );
		next_sample = current_sample + real_samples;
//		logs::log() << " next_sample = " << next_sample << " return " << real_samples << "\n";
		return real_samples;
	}
	virtual void get_data(Type channel, void * dst, int dst_stride, int dst_bits)
	{
		get_rep()->get_data( current_sample, next_sample, channel, dst, dst_stride, dst_bits );
	}
};

} // namespace noise
} // namesapce liba
using namespace liba;

#endif //__NOISE_DATA_SOURCE_WAVEFILE_H__

